package liangtWorkSpace.base.reflect;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * @author liangt
 * @Description 演示:getClass获取内部属性的操作
 * @Date 2020/12/1：12:08
 * @Version V1.0
 * @ClassName TestMain
 */
public class TestMain {


    /**
     * @return void
     * @MethodName main
     * @author liangt
     * @Description TODO
     * @Date 2020/12/1  12:08
     * @Param [args]
     */
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    }

    /**
     * @return
     * @MethodName
     * @author liangt
     * @Description 反射：利用set/get方法完成属性的注入
     * @Date 2020/12/1  12:19
     * @Param
     */
    @Test
    public void filed() throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        UserController userController = new UserController();

        //获取类内部信息
        Class<? extends UserController> clazz = userController.getClass();

        //获取UserService的属性信息
        //获取所有属性信息
        Field[] declaredFields = clazz.getDeclaredFields();

        //打印信息：private liangtWorkSpace.base.reflect.UserService liangtWorkSpace.base.reflect.UserController.userService
        Arrays.asList(declaredFields).stream().forEach(System.out::println);

        Field userServiceField = clazz.getField("userService");

        //是否允许访问内部属性
        userServiceField.setAccessible(true);

        //将名字进行驼峰
        String name = userServiceField.getName();
        name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());

        //设置get方法
        System.out.println("内部属性的名称：" + name);
        String getService = "get" + name;
        System.out.println(getService);

        //设置set方法
        String setService = "set" + name;

        //设置UserService内部属性
        Method method = clazz.getMethod(setService, UserService.class);
        UserService userService = new UserService();

        //动态代理，设置userController的userService
        method.invoke(userController, userService);

        //打印输出结果
        System.out.println(userController.getUserService());
    }

    /**
     * @return void
     * @MethodName filed2
     * @author liangt
     * @Description 反射：直接对属性进行注入
     * @Date 2020/12/1  12:20
     * @Param []
     */
    @Test
    public void filed2() throws Exception {
        UserController userController = new UserController();

        //获取类内部信息
        Class<? extends UserController> clazz = userController.getClass();

        //获取UserService的属性信息

        //获取所有属性信息
        Field[] declaredFields = clazz.getDeclaredFields();

        //打印信息：private liangtWorkSpace.base.reflect.UserService liangtWorkSpace.base.reflect.UserController.userService
        Arrays.asList(declaredFields).stream().forEach(System.out::println);

        //获取userService属性--必须是public的
        Field userServiceField = clazz.getField("userService");

        //是否允许访问内部属性
        userServiceField.setAccessible(true);

        //获取属性名称
        String name = userServiceField.getName();
        System.out.println("内部属性的名称：" + name);

        //设置内部属性
        UserService userService = new UserService();
        userServiceField.set(userController, userService);

        System.out.println(userController.getUserService());
    }

    /**
     * 演示AutoWried实现
     */
    @Test
    public void filed3(){
        UserController userController = new UserController();

        //获取class
        Class<? extends UserController> clazz = userController.getClass();


        UserService userService = new UserService();
        Stream.of(clazz.getDeclaredFields()).forEach(field -> {
            String name = field.getName();
            //如果属性存在AutoWried
            AutoWried annotation = field.getAnnotation(AutoWried.class);
            if (annotation != null){
                //不通过set注入
                field.setAccessible(true);
                Class<?> type = field.getType();
                try {
                    //new Instences默认使用无参构造
                    Object o = type.getConstructor().newInstance();
                    field.set(userController,o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                System.out.println(field.getName());
            }
        });
        System.out.println(userController.getUserService());
    }

}
